package com.cinema.util;

import javax.servlet.ServletContext;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.UUID;

/**
 * 双重文件上传工具类
 * 同时保存文件到项目源码目录和Tomcat运行目录
 */
public class DualFileUploadUtil {
    
    // 项目根目录路径
    private static final String PROJECT_ROOT = "D:\\project\\java\\cinema-booking-system\\src\\main\\webapp";
    
    /**
     * 上传结果类
     */
    public static class UploadResult {
        private boolean success;
        private String message;
        private String relativePath;
        private String sourceFilePath;
        private String runtimeFilePath;
        
        public UploadResult(boolean success, String message) {
            this.success = success;
            this.message = message;
        }
        
        public UploadResult(boolean success, String message, String relativePath, 
                          String sourceFilePath, String runtimeFilePath) {
            this.success = success;
            this.message = message;
            this.relativePath = relativePath;
            this.sourceFilePath = sourceFilePath;
            this.runtimeFilePath = runtimeFilePath;
        }
        
        // Getters
        public boolean isSuccess() { return success; }
        public String getMessage() { return message; }
        public String getRelativePath() { return relativePath; }
        public String getSourceFilePath() { return sourceFilePath; }
        public String getRuntimeFilePath() { return runtimeFilePath; }
    }
    
    /**
     * 双重保存文件
     * @param filePart 上传的文件部分
     * @param servletContext Servlet上下文
     * @param subDirectory 子目录（如 "images/movies"）
     * @return 上传结果
     */
    public static UploadResult saveFile(Part filePart, ServletContext servletContext, String subDirectory) {
        try {
            // 验证文件
            if (filePart == null || filePart.getSize() == 0) {
                return new UploadResult(false, "没有选择文件或文件为空");
            }
            
            String fileName = getFileName(filePart);
            if (fileName == null || fileName.trim().isEmpty()) {
                return new UploadResult(false, "无法获取文件名");
            }
            
            // 验证文件类型
            String contentType = filePart.getContentType();
            if (!isValidImageType(contentType)) {
                return new UploadResult(false, "只支持JPG、PNG、GIF格式的图片");
            }
            
            // 生成唯一文件名
            String fileExtension = getFileExtension(fileName);
            String uniqueFileName = UUID.randomUUID().toString() + fileExtension;
            
            // 获取两个上传目录的绝对路径
            String sourceUploadPath = PROJECT_ROOT + File.separator + subDirectory.replace("/", File.separator);
            String runtimeUploadPath = servletContext.getRealPath("") + File.separator + subDirectory.replace("/", File.separator);
            
            // 创建目录
            UploadResult dirResult = ensureDirectoriesExist(sourceUploadPath, runtimeUploadPath);
            if (!dirResult.isSuccess()) {
                return dirResult;
            }
            
            // 保存到源码目录
            String sourceFilePath = sourceUploadPath + File.separator + uniqueFileName;
            filePart.write(sourceFilePath);
            System.out.println("图片已保存到源码目录: " + sourceFilePath);
            
            // 保存到运行时目录
            String runtimeFilePath = runtimeUploadPath + File.separator + uniqueFileName;
            try {
                Files.copy(
                    Paths.get(sourceFilePath),
                    Paths.get(runtimeFilePath),
                    StandardCopyOption.REPLACE_EXISTING
                );
                System.out.println("图片已复制到运行时目录: " + runtimeFilePath);
            } catch (IOException copyEx) {
                System.err.println("复制图片到运行时目录失败: " + copyEx.getMessage());
                // 不抛出异常，因为源码目录已保存成功
            }
            
            // 返回相对路径
            String relativePath = "/" + subDirectory + "/" + uniqueFileName;
            
            return new UploadResult(true, "上传成功", relativePath, sourceFilePath, runtimeFilePath);
            
        } catch (Exception e) {
            System.err.println("文件上传失败: " + e.getMessage());
            e.printStackTrace();
            return new UploadResult(false, "上传失败: " + e.getMessage());
        }
    }
    
    /**
     * 确保目录存在
     */
    private static UploadResult ensureDirectoriesExist(String sourceUploadPath, String runtimeUploadPath) {
        // 创建源码目录
        File sourceUploadDir = new File(sourceUploadPath);
        if (!sourceUploadDir.exists()) {
            boolean created = sourceUploadDir.mkdirs();
            if (!created) {
                return new UploadResult(false, "创建源码上传目录失败: " + sourceUploadPath);
            }
            System.out.println("成功创建源码上传目录: " + sourceUploadPath);
        }
        
        // 创建运行时目录
        File runtimeUploadDir = new File(runtimeUploadPath);
        if (!runtimeUploadDir.exists()) {
            boolean created = runtimeUploadDir.mkdirs();
            if (!created) {
                return new UploadResult(false, "创建运行时上传目录失败: " + runtimeUploadPath);
            }
            System.out.println("成功创建运行时上传目录: " + runtimeUploadPath);
        }
        
        return new UploadResult(true, "目录创建成功");
    }
    
    /**
     * 删除文件（同时删除源码目录和运行时目录的文件）
     */
    public static boolean deleteFile(ServletContext servletContext, String relativePath) {
        boolean success = true;
        
        try {
            // 删除源码目录的文件
            String sourceFilePath = PROJECT_ROOT + relativePath.replace("/", File.separator);
            File sourceFile = new File(sourceFilePath);
            if (sourceFile.exists()) {
                boolean deleted = sourceFile.delete();
                if (deleted) {
                    System.out.println("已删除源码目录文件: " + sourceFilePath);
                } else {
                    System.err.println("删除源码目录文件失败: " + sourceFilePath);
                    success = false;
                }
            }
            
            // 删除运行时目录的文件
            String runtimeFilePath = servletContext.getRealPath("") + relativePath.replace("/", File.separator);
            File runtimeFile = new File(runtimeFilePath);
            if (runtimeFile.exists()) {
                boolean deleted = runtimeFile.delete();
                if (deleted) {
                    System.out.println("已删除运行时目录文件: " + runtimeFilePath);
                } else {
                    System.err.println("删除运行时目录文件失败: " + runtimeFilePath);
                    success = false;
                }
            }
            
        } catch (Exception e) {
            System.err.println("删除文件时发生异常: " + e.getMessage());
            e.printStackTrace();
            success = false;
        }
        
        return success;
    }
    
    /**
     * 获取文件名
     */
    private static String getFileName(Part part) {
        String contentDisposition = part.getHeader("content-disposition");
        if (contentDisposition != null) {
            for (String content : contentDisposition.split(";")) {
                if (content.trim().startsWith("filename")) {
                    return content.substring(content.indexOf('=') + 1).trim().replace("\"", "");
                }
            }
        }
        return null;
    }
    
    /**
     * 获取文件扩展名
     */
    private static String getFileExtension(String fileName) {
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex > 0) {
            return fileName.substring(lastDotIndex);
        }
        return "";
    }
    
    /**
     * 验证是否为有效的图片类型
     */
    private static boolean isValidImageType(String contentType) {
        return contentType != null && (
            contentType.equals("image/jpeg") ||
            contentType.equals("image/jpg") ||
            contentType.equals("image/png") ||
            contentType.equals("image/gif") ||
            contentType.equals("image/webp")
        );
    }
    
    /**
     * 格式化文件大小
     */
    public static String formatFileSize(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return String.format("%.1f KB", bytes / 1024.0);
        } else if (bytes < 1024 * 1024 * 1024) {
            return String.format("%.1f MB", bytes / (1024.0 * 1024.0));
        } else {
            return String.format("%.1f GB", bytes / (1024.0 * 1024.0 * 1024.0));
        }
    }
    
    /**
     * 获取项目根目录
     */
    public static String getProjectRoot() {
        return PROJECT_ROOT;
    }
}
